home *** CD-ROM | disk | FTP | other *** search
- /*
- * CBLibrary - InputFocus
- * Copyright (C) 2003 Chris Bazley
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- /*
- * Code to record the caret position prior to opening transient
- * dboxes (e.g. on Window_AboutToBeShown event), and restore it when
- * the menu tree is closed (if no other window has taken it).
- * It can be used to work around a bug in the Toolbox: When closed,
- * transient windows with default input focus in the window background
- * do not restore the caret to the window from which they borrowed it.
- */
-
- #ifndef NDEBUG
- #include <stdio.h>
- #include "kernel.h"
- #endif
-
- #include "wimp.h"
- #include "wimplib.h"
- #include "event.h"
- #include "window.h"
- #include "menu.h"
- #include "DCS.h"
- #include "Quit.h"
-
- #include "InputFocus.h"
- #include "err.h"
- #include "Macros.h"
-
- /* N.B. there can be only one transient dbox open at a time */
- static WimpCaret caret_store;
- static int window_handle = -1; /* not a valid window handle */
-
- /* ----------------------------------------------------------------------- */
- /* Function prototypes */
-
- static WimpMessageHandler _InputFocus_menusdeleted;
-
- /* ----------------------------------------------------------------------- */
- /* Public functions */
-
- _kernel_oserror *InputFocus_initialise(void)
- {
- return event_register_message_handler(Wimp_MMenusDeleted, _InputFocus_menusdeleted, NULL);
- }
-
- /* ----------------------------------------------------------------------- */
-
- int InputFocus_recordcaretpos(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- /* Can only handle those classes for which we know how to get window
- handle. Also, the AboutToBeShown event blocks for these 3 have a
- common structure */
- NOT_USED(handle)
-
- ObjectId window_id;
- switch(event_code) {
- case DCS_AboutToBeShown:
- E_RETV(dcs_get_window_id(0, id_block->self_id, &window_id), 0)
- break;
-
- case Quit_AboutToBeShown:
- E_RETV(quit_get_window_id(0, id_block->self_id, &window_id), 0)
- break;
-
- case Window_AboutToBeShown:
- window_id = id_block->self_id;
- break;
-
- default:
- return 0;
- }
-
- /* Check that we are being shown transiently - otherwise we might let
- ourselves in for a whole heap of trouble */
- if(!FLAG_SET(event->hdr.flags, Toolbox_ShowObject_AsMenu))
- return 0;
-
- /* Is this dbox hanging off a menu tree? */
- ObjectClass parent_class = 0;
- if(id_block->parent_id != NULL_ObjectId)
- /* parent may have been deleted, so ignore error return */
- toolbox_get_object_class(0, id_block->parent_id, &parent_class);
-
- if(parent_class == Menu_ObjectClass)
- /* don't attempt to match window handle */
- window_handle = -2;
- else
- /* No - record window handle to compare against MenusDeleted message */
- RE(window_get_wimp_handle(0, window_id, &window_handle))
-
- RE(wimp_get_caret_position(&caret_store))
- #ifndef NDEBUG
- sprintf(string, "report recording caret pos: %d, %d, %d, %d, %d, %d prior to opening window %d (wimp handle %d)", ((WimpCaret *)handle)->window_handle, ((WimpCaret *)handle)->icon_handle, ((WimpCaret *)handle)->xoffset, ((WimpCaret *)handle)->yoffset, ((WimpCaret *)handle)->height, ((WimpCaret *)handle)->index, id_block->self_id, window_handle);
- _kernel_oscli(string);
- #endif
-
- return 0; /* don't claim event */
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *InputFocus_restorecaret(void)
- {
- /* Find current caret position */
- WimpGetCaretPositionBlock now_pos;
- THROW(wimp_get_caret_position(&now_pos))
- #ifndef NDEBUG
- sprintf(string, "report post-close caret pos: %d, %d, %d, %d, %d, %d", now_pos.window_handle, now_pos.icon_handle, now_pos.xoffset, now_pos.yoffset, now_pos.height, now_pos.index);
- _kernel_oscli(string);
- #endif
-
- /* Attempt to restore the input focus (if no window has claimed it)
- Ignore any error, cos it probably means previous owner is dead */
- if(now_pos.window_handle == -1)
- wimp_set_caret_position(caret_store.window_handle, caret_store.icon_handle, caret_store.xoffset, caret_store.yoffset, caret_store.height, caret_store.index);
- return NULL;
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private functions */
-
- int _InputFocus_menusdeleted(WimpMessage *message, void *handle)
- {
- NOT_USED(handle)
- #ifndef NDEBUG
- char string[255];
- sprintf(string, "report Message_MenusDeleted received for %d", message->words[0]);
- _kernel_oscli(string);
- #endif
-
- if(message->data.words[0] == window_handle || window_handle == -2) {
- /* Our dbox has just closed or we don't care about handle */
- window_handle = -1;
-
- RE(InputFocus_restorecaret());
- }
-
- return 0; /* don't claim event */
- }
-